use std::env::args;
use std::time::Duration;
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, Ordering};
use std::io::Read;
use std::io::{Write, Error};
use std::thread;
use std::sync::mpsc::{self};
use std::mem::size_of;
use std::convert::TryInto;
use std::fs::File;
use std::path::Path;



use serialport::{ DataBits, FlowControl, Parity, SerialPort, StopBits};

fn parseArgs(args:Vec<String>) -> Vec<(String, Option<String>)>
{
    let mut parse_result :Vec<(String, Option<String>)>= Vec::new();
    let mut args_iter = args.into_iter().skip(1);

    while let Some(arg) = args_iter.next()
    {
        println!("{}", arg);
        if let Some(param_name) = arg.strip_prefix('-')
        {
            let param_name = param_name.to_string();
            let next_arg = args_iter.next();
            println!("{:?}",next_arg);
            let param_value = if let Some(next_arg) = next_arg.as_ref()
            {
                if !next_arg.starts_with('-')
                {
                    Some(next_arg.clone())
                }
                else {
                    None
                }
            }
            else
            {
                None
            };
            parse_result.push((param_name, param_value));
        }
        else {
            println!("error parameter format, you should start with \'-\'");
        }
    }
    parse_result
}

struct serial_port_attribute
{
    baud: u32,
    port: Option<String>,
    data_bits: DataBits,
    flow_control: FlowControl,
    stop_bits: StopBits,
    parity: Parity,
}

type argCallback = fn(&mut serial_port_attribute, Option<String>) -> Result<(),i32>;

fn SerialPortSetPort(attr: &mut serial_port_attribute, arg:Option<String>) -> Result<(),i32>
{
    match arg {
        Some(arg) => {
            attr.port = Some(arg);
            Ok(())
       }
       None => {
        attr.port = None;
        Err(-1)
       }
    }
}
fn SerialPortSetBaud(attr: &mut serial_port_attribute, arg:Option<String>) -> Result<(),i32>
{
    match arg
    {
        Some(arg) =>
        {
            attr.baud = arg.parse().unwrap();
            Ok(())
        }
        None =>{
            Err(-1)
        }
    }
}

fn SerialPortSetParity(attr: &mut serial_port_attribute, arg:Option<String>) -> Result<(),i32>
{
    match arg
    {
        Some(arg) =>
        {
            match arg.as_str(){
                "0" => 
                {
                    attr.parity = Parity::None;
                    Ok(())
                }
                "1" => 
                {
                    attr.parity = Parity::Odd;
                    Ok(())
                }
                "2" => 
                {
                    attr.parity = Parity::Even;
                    Ok(())
                }
                _ =>
                {
                    println!("Error parity specified!(0:None,1:Odd,2:Even)");
                    Err(-2)
                }

            }
        }
        None =>{
            println!("No parity specified!(0:None,1:Odd,2:Even)");
            Err(-1)
        }
    }
}

fn SerialPortSetStopBits(attr: &mut serial_port_attribute, arg:Option<String>) -> Result<(),i32>
{
    match arg
    {
        Some(arg) =>
        {
            match arg.as_str(){
                "1" => 
                {
                    attr.stop_bits = StopBits::One;
                    Ok(())
                }
                "2" => 
                {
                    attr.stop_bits = StopBits::Two;
                    Ok(())
                }
                _ =>
                {
                    println!("Error stopbits specified!(1:One bit,2: Two bits)");
                    Err(-2)
                }

            }
        }
        None =>{
            println!("No parity specified!(1:One bit,2: Two bits)");
            Err(-1)
        }
    }
}

fn SerialPortSetFlowControl(attr: &mut serial_port_attribute, arg:Option<String>) -> Result<(),i32>
{
    match arg
    {
        Some(arg) =>
        {
            match arg.as_str(){
                "N" => 
                {
                    attr.flow_control = FlowControl::None;
                    Ok(())
                }
                "H" => 
                {
                    attr.flow_control = FlowControl::Hardware;
                    Ok(())
                }
                "S" => 
                {
                    attr.flow_control = FlowControl::Software;
                    Ok(())
                }
                _ =>
                {
                    println!("Error flowcontrol specified!(N:None, H:Hardware, S: Software)");
                    Err(-2)
                }

            }
        }
        None =>{
            println!("No flowcontrol specified!(N:None, H:Hardware, S: Software)");
            Err(-1)
        }
    }
}

static CMD_TABLE:&[(&str, argCallback)] = &[
    ("b", SerialPortSetBaud),
    ("D", SerialPortSetPort),
    ("s", SerialPortSetStopBits),
    ("p", SerialPortSetParity),
    ("f", SerialPortSetFlowControl),
];

impl serial_port_attribute
{
    fn new() -> serial_port_attribute
    {
        serial_port_attribute{
            baud : 115200,
            data_bits : DataBits::Eight,
            flow_control : FlowControl::None,
            parity : Parity::None,
            stop_bits : StopBits::One,
            port : None,
        }
    }
}

fn openSerialPortFromArgs(args :Vec<String>) -> Result<Box<dyn SerialPort>,i32>
{
    let mut attr: serial_port_attribute = serial_port_attribute::new();
    let mut matched = None;
    let arg_list = parseArgs(args);
    for (param_name, value ) in arg_list{
        for (cmd, cb) in CMD_TABLE
        {
            if *cmd == param_name.as_str()
            {
                let callback_result = cb(&mut attr, value);
                match callback_result
                {
                    Ok(()) => 
                    {
                        matched = Some(0);
                    }
                    Err(e) => 
                    {
                        matched = Some(e);
                    }
                }
                break;
            }
            if !(None == matched)
            {
                break;
            }
        }
    }
    if Some(0) != matched
    {
        match matched
        {
            Some(e)=>
            {
                println!("Unrecgonize param or error vale detected!");
                Err(e)  
            }
            None=>
            {
                println!("No param, -D param is required");
                Err(0)
            }
        }
    }
    else {
        match attr.port{
            None =>
            {
                println!("No param, -D param is required");
                Err(1)
            }
            Some(e)=>
            {
                let port = serialport::new(e.as_str(), attr.baud)
                                        .stop_bits(attr.stop_bits)
                                        .flow_control(attr.flow_control)
                                        .parity(attr.parity)
                                        .data_bits(attr.data_bits)
                                        .open().unwrap();
                Ok(port)
            }
        }
    }
}

// 定义单个传感器的数据结构
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct SensorData {
    pub wear_res: [u16; 4],      // 4个u16电阻值
    pub wear_diff: [i16; 2],     // 2个有符号差分值
    pub proximate: u8,           // 接近检测值
    pub temp: u8,                // 温度值
}

// 常量定义
const HEADER_SIZE: usize = size_of::<u8>() * 2;  // packet_id(1) + len(1)
const GROUP_SIZE: usize = 14;                    // 每组数据长度
const GROUPS_COUNT: usize = 15;                  // 数据组数量
const EXPECTED_LEN: u8 = (GROUPS_COUNT * GROUP_SIZE) as u8; // 0xD2

impl SensorData {
    /// 从字节切片中解析单个传感器数据
    fn from_bytes(data: &[u8]) -> Result<Self, &'static str> {
        // 确保切片有足够长度
        if data.len() < GROUP_SIZE {
            return Err("Invalid group length");
        }
        
        let mut offset = 0;
        
        // 解析 wear_res（4个u16小端序）
        let mut wear_res = [0u16; 4];
        for i in 0..4 {
            let bytes = data[offset..offset+2].try_into().expect("u16 slice");
            wear_res[i] = u16::from_le_bytes(bytes);
            offset += 2;
        }
        
        // 解析 wear_diff（2个i16小端序）
        let mut wear_diff = [0i16; 2];
        for i in 0..2 {
            let bytes = data[offset..offset+2].try_into().expect("i16 slice");
            wear_diff[i] = i16::from_le_bytes(bytes);
            offset += 2;
        }
        
        // 解析 proximate 和 temp
        let proximate = data[offset];
        offset += 1;
        let temp = data[offset];
        
        Ok(SensorData {
            wear_res,
            wear_diff,
            proximate,
            temp,
        })
    }
}

/// 解析传感器数据包
pub fn parse_sensor_data(raw: &[u8]) -> Result<(u8, Vec<SensorData>), &'static str> {
    // 验证总长度
    let expected_total_size = HEADER_SIZE + (GROUP_SIZE * GROUPS_COUNT);
    if raw.len() < expected_total_size {
        return Err("Packet too short");
    }
    
    // 解析包头
    let packet_id = raw[0];
    let len = raw[1];
    
    // 验证长度字段
    if len != EXPECTED_LEN {
        return Err("Invalid length field");
    }
    
    // 解析所有数据组
    let start_index = HEADER_SIZE;
    let mut sensor_data = Vec::with_capacity(GROUPS_COUNT);
    
    for group_index in 0..GROUPS_COUNT {
        let start = start_index + group_index * GROUP_SIZE;
        let end = start + GROUP_SIZE;
        
        match SensorData::from_bytes(&raw[start..end]) {
            Ok(data) => sensor_data.push(data),
            Err(e) => return Err(e),
        }
    }
    
    Ok((packet_id, sensor_data))
}

pub fn save_sensor_data_to_csv(data: &[SensorData], path: &Path) -> Result<(), Error> {
    let mut file = File::create(path)?;
    
    file.write_all(b"wear0,wear0_ref,wear1,wear1_ref,")?;
    file.write_all(b"wear_diff_0,wear_diff_1,")?;
    file.write_all(b"proximate,temp\n")?;
    
    for sensor in data {
        let row = format!(
            "{},{},{},{},{},{},{},{}\n",
            sensor.wear_res[0],
            sensor.wear_res[1],
            sensor.wear_res[2],
            sensor.wear_res[3],
            sensor.wear_diff[0],
            sensor.wear_diff[1],
            sensor.proximate,
            sensor.temp
        );
        file.write_all(row.as_bytes())?;
    }
    
    file.flush()?;
    Ok(())
}

fn main() {
    // capture Ctrl-C
    let running = Arc::new(AtomicBool::new(true));
    let port = openSerialPortFromArgs(args().collect()).unwrap();
    let mut output_file = String::from("./output/sensor.csv");
    {
        let arg_lists = parseArgs(args().collect());
        for (name, value) in arg_lists{
            if name.as_str() == "o"
            {
                if let Some(file) = value
                {
                    output_file.clear();
                    output_file.push_str(file.as_str());
                }
                else {
                    println!("-o need a param");
                }
            }
            else{}
        }
    }
    let port_mutex = Arc::new(Mutex::new(port));
    let (tx,rx):(mpsc::Sender<i32>,mpsc::Receiver<i32>) = mpsc::channel();
    let is_running_clone = Arc::clone(&running);

    let sensor_data_store_list  = Arc::new(Mutex::new(Vec::<SensorData>::new()));
    let data_list_clone = sensor_data_store_list.clone();

    ctrlc::set_handler(move || {
        println!("Received CTRL-C, save csv...");
        let running_clone = Arc::clone(&running);
        running_clone.store(false, Ordering::Relaxed);
    }).expect("Set Ctrl-C handler error");

    let handle = thread::spawn(move ||{
        let mut serial_buf:Vec<u8> = vec![0;2048];
        let mut port_instance = port_mutex.lock().unwrap();
        let mut last_packet_id:u8 = 0;
        while is_running_clone.load(Ordering::Relaxed)
        {
            match port_instance.read(serial_buf.as_mut_slice()) 
            {
                Ok(t) => 
                {
                    if t > 0
                    {

                        match parse_sensor_data(&serial_buf[..t])
                        {
                            Ok((id,mut data_list)) =>
                            {
                                println!("packid={},last_id={}", id, last_packet_id);
                                let mut locked_list = sensor_data_store_list.lock().unwrap();
                                locked_list.append(& mut data_list);
                                last_packet_id = id;
                            }
                            Err(e) =>
                            {
                                println!("{}",e);
                            }
                        }
                        //let recv = String::from_utf8_lossy(&serial_buf[..t]);
                        //print!("{}",recv);
                    }
                    else{}
                }
                Err(ref e) if e.kind() == std::io::ErrorKind::TimedOut => {}
                Err(e) =>
                {
                    println!("读取错误:{}", e);
                }
            }
            thread::sleep(Duration::from_millis(211));
        }
    });
    drop(tx);
    handle.join().unwrap();
    println!("saving csv");
    let locked_list = data_list_clone.lock().unwrap();
    let _ =save_sensor_data_to_csv(&(&locked_list), Path::new(output_file.as_str()));
    println!("CSV Saved");
    // rx.iter().next(); 
    for receiver in rx{
        println!("Got:{}", receiver);
    }
}
